/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.lang.String;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
 *
 * @author VuTran
 */
public class Enumerated extends Domain {

    List<String> ls;
    
    public List<String> getItems() {
        return ls;
    }
    
    public void setItems(List<String> items) {
        ls = items;
    }
   
    public Enumerated() {
        ls = new ArrayList<String>();
    } 
    public Enumerated(List<String> array) {
        this();
        for (String str : array) {
            ls.add(str);
        }
    }
    
    // get the length of the longest string
    public int getLength() {
        int i = 0;
        for (String str : ls) {
            if (str.length() > i) {
                i = str.length();
            }
        }
        return i;
    }
    
    @Override
    public boolean validate(Object o) {
        if (!(o instanceof String)) return false;
        if (ls.contains((String) o)) return true;
        return false;
    }

    @Override
    public Object convertString(String s) throws DomainConversionException {
        if (ls.contains(s)) return s;
        
        throw new DomainConversionException("String value " + s + " is not a value in this Enumerated type.");
    }

    @Override
    public Class getNaiveType() {
        return String.class;
    }

    @Override
    public String getDBType() {
        return "varchar(" + this.getLength() + ")";
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Enumerated)) return false;
        if (((Enumerated) obj).ls.size() != this.ls.size()) return false;
        for (int i = 0; i < this.ls.size(); i++) {
            if (!((Enumerated) obj).ls.get(i).equals(this.ls.get(i))) return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int temp = Enumeration.class.hashCode();
        for (String str : ls) {
            temp += str.hashCode();
        }
        return temp;
    }

    @Override
    public String toString() {
        return "Enumerated";
    }

    
    @Override
    public Domain upcast() {
        return new edu.pdx.cs.guavadata.domain.String(this.getLength());
    }

    @Override
    public Object upcastValue(Object o) throws Exception {
        return o;
    }

    @Override
    public Domain merge(Domain d) {
        if (!(d instanceof Enumerated)) return null;
        Enumerated e = new Enumerated();
        for (String str : ls) {
            e.ls.add(str);
        }
        for (String str : ((Enumerated) d).ls) {
            if (!(e.ls.contains(str))) {
                e.ls.add(str);
            }
        }
        
        Collections.sort(ls);
        return e;
    }

    @Override
    public List<Object> listOutput() {
        return new ArrayList<Object>(ls); 
    }

    
    @Override
    public boolean isOrdered() {
        return false;
    }

    @Override
    public boolean canContain() {
        return false;
    }

    @Override
    public Domain clone() {
        return new Enumerated(new ArrayList<String>(this.getItems()));
    }

    @Override
    public Element ToXml(Document xdoc) {
        Element xe = xdoc.createElement("Domain");
        xe.setAttribute("Type", "Enumerated");
        for (String str : ls) {
            Element item = xdoc.createElement("Item");
            Text xt = xdoc.createTextNode(str);
            item.appendChild(xt);
            xe.appendChild(item);
        }
        return xe;
    }

    public static Enumerated fromElement(Element e) {
        Enumerated o = new Enumerated();
        o.ls = new ArrayList<String>();
        NodeList itemList = e.getChildNodes();
        for (int i = 0; i < itemList.getLength(); i++) {
            if (itemList.item(i).getNodeName().equals("Item"))
                o.ls.add(itemList.item(i).getFirstChild().getNodeValue());
        }
        return o;
    }
}
